/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ruter.visual;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import ruter.map.Map;
import ruter.map.MapException;
import ruter.map.PathSection;

/**
 * This class is used to handle the map functions.
 * @author Camilo Ortegon
 */
public class MapDrawer {

	public Map map;
	private double pixelSize;
	public int xWindow, yWindow;
	private Color streetColor = Color.gray;
	private Color streetLineColor = Color.white;

	/**
	 * Canvas to paint
	 */
	private BufferedImage canvas;
	private Graphics graphics;

	/**
	 * Static part of the canvas. For example the streets.
	 */
	private BufferedImage staticPartCanvas;
	private Graphics staticPartGraphics;

	public MapDrawer(Map map) {
		this.map = map;
		this.pixelSize = 1;
	}

	public void setPixelSize(double pixelSize) {
		this.pixelSize = pixelSize;
	}

	private void startCanvas(int width, int height) {
		canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		graphics = canvas.getGraphics();
		graphics.setColor(Color.white);
		graphics.fillRect(0, 0, width, height);
	}

	private void startStaticPartCanvas(int width, int height) {
		staticPartCanvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		staticPartGraphics = staticPartCanvas.getGraphics();
		staticPartGraphics.setColor(Color.white);
		staticPartGraphics.fillRect(0, 0, width, height);
	}

	public void move(int xMove, int yMove) {
		this.xWindow += xMove;
		this.yWindow += yMove;
	}

	public void makePath(int x, int y, double lanWidth, int leftLanes, int rightLanes) throws MapException {
		map.makePath((x-xWindow)*pixelSize, (y-yWindow)*pixelSize, lanWidth, leftLanes, rightLanes);
	}

	public void paint(Graphics g) {
		g.drawImage(canvas, 0, 0, null);
	}

	private void repaintStaticPartOfTheCanvas(int width, int height) {

		startStaticPartCanvas(width, height);

		staticPartGraphics.setColor(streetColor);
		for (int i = 0; i < map.heads.size(); i++) {
			PathSection lastP = map.heads.get(i);
			while(lastP.next != null) {
				PathSection frontP = lastP.next;
				int street[][] = generateStreetSquare(lastP, frontP, xWindow, yWindow, width, height);
				if(street != null)
					staticPartGraphics.fillPolygon(street[0], street[1], 4);
				//                else
					//                    System.out.println("No se ve");
				lastP = frontP;
			}
		}

		for (int i = 0; i < map.heads.size(); i++) {
			PathSection lastP = map.heads.get(i);
			while(lastP.next != null) {
				PathSection frontP = lastP.next;
				staticPartGraphics.setColor(Color.red);
				staticPartGraphics.drawLine((int)(lastP.x*pixelSize)-xWindow, (int)(lastP.y*pixelSize)-yWindow,
						(int)(frontP.x*pixelSize)-xWindow, (int)(frontP.y*pixelSize)-yWindow);
				staticPartGraphics.setColor(Color.blue);

				for (int j = 0; j < lastP.lanPoints.length; j++) {
					staticPartGraphics.drawLine((int)(lastP.lanPoints[j][0]*pixelSize)-xWindow, (int)(lastP.lanPoints[j][1]*pixelSize)-yWindow,
							(int)(frontP.arrivingLanPoints[j][0]*pixelSize)-xWindow, (int)(frontP.arrivingLanPoints[j][1]*pixelSize)-yWindow);
				}
				lastP = frontP;
			}
		}
	}

	public void repaint(Graphics g, int width, int height) {

		if(staticPartCanvas == null)
			repaintStaticPartOfTheCanvas(width, height);
		g.drawImage(staticPartCanvas, 0, 0, null);

	}

	private int[][] generateStreetSquare(PathSection p1, PathSection p2, int x, int y, int width, int height) {

		int street[][] = new int[2][4];

		street[0][0] = (int)(p1.borders[0][0]*pixelSize-x);
		street[1][0] = (int)(p1.borders[0][1]*pixelSize-y);
		street[0][1] = (int)(p1.borders[1][0]*pixelSize-x);
		street[1][1] = (int)(p1.borders[1][1]*pixelSize-y);
		street[0][3] = (int)(p2.arrivingBorder[0][0]*pixelSize-x);
		street[1][3] = (int)(p2.arrivingBorder[0][1]*pixelSize-y);
		street[0][2] = (int)(p2.arrivingBorder[1][0]*pixelSize-x);
		street[1][2] = (int)(p2.arrivingBorder[1][1]*pixelSize-y);

		int minX = street[0][0];
		if(street[0][1] < minX)
			minX = street[0][1];
		if(street[0][2] < minX)
			minX = street[0][2];
		if(street[0][3] < minX)
			minX = street[0][3];

		int minY = street[1][0];
		if(street[1][1] < minY)
			minY = street[1][1];
		if(street[1][2] < minY)
			minY = street[1][2];
		if(street[1][3] < minY)
			minY = street[1][3];

		if(minX < width && minY < height)
			return street;
		else
			return null;
	}

}
